/**
 * TouchSlider v1.3.1
 * By qiqiboy, http://www.qiqiboy.com, http://weibo.com/qiqiboy, 2013/08/30
 */
(function(J, K) {
    "use strict";
    var F = ("createTouch" in document) || ("ontouchstart" in J),
    H = document.createElement("div").style,
    D = (function() {
        var $ = {
            OTransform: ["-o-", "otransitionend"],
            WebkitTransform: ["-webkit-", "webkitTransitionEnd"],
            MozTransform: ["-moz-", "transitionend"],
            msTransform: ["-ms-", "MSTransitionEnd"],
            transform: ["", "transitionend"]
        },
        _;
        for (_ in $) if (_ in H) return $[_];
        return false
    })(),
    I = [["width", "left", "right"], ["height", "top", "bottom"]],
    L = D && D[0],
    B = function($) {
        return ($ + "").replace(/^-ms-/, "ms-").replace(/-([a-z]|[0-9])/ig,
        function(_, $) {
            return ($ + "").toUpperCase()
        })
    },
    C = function($) {
        var _ = B(L + $);
        return ($ in H) && $ || (_ in H) && _
    },
    G = function(_, $) {
        for (var A in $) if (typeof _[A] == "undefined") _[A] = $[A];
        return _
    },
    E = function($) {
        var A = $.children || $.childNodes,
        _ = [],
        B = 0;
        for (; B < A.length; B++) if (A[B].nodeType === 1) _.push(A[B]);
        return _
    },
    M = function($, _) {
        var B = 0,
        A = $.length;
        for (; B < A; B++) if (_.call($[B], B, $[B]) === false) break
    },
    $ = function($) {
        $ = _.fn.eventHook($);
        $.preventDefault()
    },
    A = D[1] || "",
    _ = function($, A) {
        if (! (this instanceof _)) return new _($, A);
        if (typeof $ != "string" && !$.nodeType) {
            A = $;
            $ = A.id
        }
        if (!$.nodeType) $ = document.getElementById($);
        this.cfg = G(A || {},
        this._default);
        this.element = $;
        if (this.element) {
            this.container = this.element.parentNode || document.body;
            this.setup()
        }
    };
    _.fn = _.prototype = {
        version: "1.3.1",
        _default: {
            id: "slider",
            begin: 0,
            auto: true,
            speed: 600,
            timeout: 5000,
            direction: "left",
            align: "center",
            fixWidth: true,
            mouseWheel: false,
            mouseDrag: true,
            before: new Function,
            after: new Function
        },
        css: function($, D) {
            if (typeof D == "string") {
                var _ = document.defaultView && document.defaultView.getComputedStyle && getComputedStyle($, null) || $.currentStyle || $.style || {};
                return _[B(D)]
            } else {
                var A, C;
                for (A in D) {
                    if (A == "float") C = ("cssFloat" in H) ? "cssFloat": "styleFloat";
                    else C = B(A);
                    $.style[C] = D[A]
                }
            }
        },
        addListener: function(_, A, B, $) {
            if (_.addEventListener) {
                _.addEventListener(A, B, $);
                return true
            } else if (_.attachEvent) {
                _.attachEvent("on" + A, B);
                return true
            }
            return false
        },
        removeListener: function(_, A, B, $) {
            if (_.addEventListener) {
                _.removeEventListener(A, B, $);
                return true
            } else if (_.attachEvent) {
                _.detachEvent("on" + A, B);
                return true
            }
            return false
        },
        eventHook: function(B) {
            var _ = {},
            C = "changedTouches touches scale target view which clientX clientY fromElement offsetX offsetY pageX pageY toElement".split(" ");
            B = B || J.event;
            M(C,
            function() {
                _[this] = B[this]
            });
            _.target = B.target || B.srcElement || document;
            if (_.target.nodeType === 3) _.target = _.target.parentNode;
            _.preventDefault = function() {
                B.preventDefault && B.preventDefault();
                _.returnValue = B.returnValue = false
            };
            _.stopPropagation = function() {
                B.stopPropagation && B.stopPropagation();
                _.cancelBubble = B.cancelBubble = true
            };
            if (F && _.touches.length) {
                _.pageX = _.touches.item(0).pageX;
                _.pageY = _.touches.item(0).pageY
            } else if (typeof B.pageX == "undefined") {
                var A = document.documentElement,
                $ = document.body;
                _.pageX = B.clientX + (A && A.scrollLeft || $ && $.scrollLeft || 0) - (A && A.clientLeft || $ && $.clientLeft || 0);
                _.pageY = B.clientY + (A && A.scrollTop || $ && $.scrollTop || 0) - (A && A.clientTop || $ && $.clientTop || 0)
            }
            _.origEvent = B;
            return _
        },
        bind: function(_, $) {
            return function() {
                return _.apply($, arguments)
            }
        },
        setup: function() {
            var C = F || !this.cfg.mouseDrag,
            _ = C ? "touchstart": "mousedown",
            B = C ? "touchmove": "mousemove",
            $ = C ? "touchend": "mouseup";
            this.slides = E(this.element);
            this.length = this.slides.length;
            this.cfg.timeout = parseInt(this.cfg.timeout);
            this.cfg.speed = parseInt(this.cfg.speed);
            this.cfg.begin = parseInt(this.cfg.begin);
            this.cfg.auto = !!this.cfg.auto;
            this.cfg.timeout = Math.max(this.cfg.timeout, this.cfg.speed);
            this.touching = !!F;
            this.css3transition = !!D;
            this.index = this.cfg.begin < 0 || this.cfg.begin >= this.length ? 0 : this.cfg.begin;
            if (this.length < 1) return false;
            this.comment = document.createComment("\n Powered by TouchSlider v" + this.version + ",\n author: qiqiboy,\n email: imqiqiboy@gmail.com,\n blog: http://www.qiqiboy.com,\n weibo: http://weibo.com/qiqiboy\n");
            this.container.insertBefore(this.comment, this.element);
            switch (this.cfg.direction) {
            case "up":
            case "down":
                this.direction = this.cfg.direction;
                this.vertical = 1;
                break;
            case "right":
                this.direction = "right";
            default:
                this.direction = this.direction || "left";
                this.vertical = 0;
                break
            }
            this.addListener(this.element, _, this.bind(this._start, this), false);
            this.addListener(document, B, this.bind(this._move, this), false);
            this.addListener(document, $, this.bind(this._end, this), false);
            this.addListener(document, "touchcancel", this.bind(this._end, this), false);
            this.addListener(this.element, A, this.bind(this.transitionend, this), false);
            this.addListener(J, "resize", this.bind(function() {
                clearTimeout(this.resizeTimer);
                this.resizeTimer = setTimeout(this.bind(this.resize, this), 100)
            },
            this), false);
            if (this.cfg.mouseWheel) {
                this.addListener(this.element, "mousewheel", this.bind(this.mouseScroll, this), false);
                this.addListener(this.element, "DOMMouseScroll", this.bind(this.mouseScroll, this), false)
            }
            this.playing = this.cfg.auto;
            this.resize()
        },
        getSum: function(C, _, D) {
            var A = 0,
            E = _,
            $ = B("-" + C);
            for (; E < D; E++) A += this["getOuter" + $](this.slides[E]);
            return A
        },
        getPos: function(D, A) {
            var _ = B("-" + D),
            $ = this.getSum(D, A, A + 1),
            C = this.getSum(D, 0, A) + this["getOuter" + _](this.element) / 2 - this["get" + _](this.element) / 2;
            switch (this.cfg.align) {
            case "left":
                return - C;
            case "right":
                return this[D] - $ - C;
            default:
                return (this[D] - $) / 2 - C
            }
        },
        resize: function() {
            clearTimeout(this.aniTimer);
            var A = this,
            D, C = I[this.vertical][0],
            $ = B("-" + C),
            _ = this.css(this.container, "position");
            this.css(this.container, {
                overflow: "hidden",
                visibility: "hidden",
                listStyle: "none",
                position: _ == "static" ? "relative": _
            });
            this[C] = this["get" + $](this.container);
            D = {
                float: this.vertical ? "none": "left",
                display: "block"
            };
            M(this.slides,
            function() {
                if (A.cfg.fixWidth) D[C] = A[C] - A["margin" + $](this) - A["padding" + $](this) - A["border" + $](this) + "px";
                A.css(this, D)
            });
            this.total = this.getSum(C, 0, this.length);
            D = {
                position: "relative",
                overflow: "hidden"
            };
            D[L + "transition-duration"] = "0ms";
            D[C] = this.total + "px";
            D[I[this.vertical][1]] = this.length ? this.getPos(C, this.index) + "px": 0;
            this.css(this.element, D);
            this.css(this.container, {
                visibility: "visible"
            });
            this.playing && this.play();
            return this
        },
        slide: function($, A) {
            var B = I[this.vertical][1],
            H = I[this.vertical][0],
            F = C("transition"),
            M = parseFloat(this.css(this.element, B)) || 0,
            O,
            P = {},
            D,
            J = this.getSum(H, $, $ + 1);
            $ = Math.min(Math.max(0, $), this.length - 1);
            A = typeof A == "undefined" ? this.cfg.speed: parseInt(A);
            O = this.getPos(H, $);
            D = O - M,
            A = Math.abs(D) < J ? Math.ceil(Math.abs(D) / J * A) : A;
            if (F) {
                P[F] = B + " ease " + A + "ms";
                P[B] = O + "px";
                this.css(this.element, P)
            } else {
                var N = this,
                K = 0,
                L = A / 10,
                _ = function(_, A, B, $) {
                    return - B * ((_ = _ / $ - 1) * _ * _ * _ - 1) + A
                },
                G = function() {
                    if (K < L) {
                        K++;
                        N.element.style[B] = Math.ceil(_(K, M, D, L)) + "px";
                        N.aniTimer = setTimeout(G, 10)
                    } else {
                        N.element.style[B] = O + "px";
                        N.transitionend({
                            propertyName: B
                        })
                    }
                };
                clearTimeout(this.aniTimer);
                G()
            }
            var E = this.slides[this.index];
            this.index = $;
            this.cfg.before.call(this, $, E);
            return this
        },
        play: function() {
            clearTimeout(this.timer);
            this.playing = true;
            this.timer = setTimeout(this.bind(function() {
                this.direction == "left" || this.direction == "up" ? this.next() : this.prev()
            },
            this), this.cfg.timeout);
            return this
        },
        pause: function() {
            clearTimeout(this.timer);
            this.playing = false;
            return this
        },
        stop: function() {
            this.pause();
            return this.slide(0)
        },
        prev: function(A, _) {
            clearTimeout(this.timer);
            var $ = this.index;
            A = typeof A == "undefined" ? A = 1 : A % this.length;
            $ -= A;
            if (_ === false) $ = Math.max($, 0);
            else $ = $ < 0 ? this.length + $: $;
            return this.slide($)
        },
        next: function(A, _) {
            clearTimeout(this.timer);
            var $ = this.index;
            if (typeof A == "undefined") A = 1;
            $ += A;
            if (_ === false) $ = Math.min($, this.length - 1);
            else $ %= this.length;
            return this.slide($)
        },
        _start: function(A) {
            A = this.eventHook(A);
            var _ = A.target.nodeName.toLowerCase();
            if (!this.touching && (_ == "a" || _ == "img")) A.preventDefault();
            this.removeListener(this.element, "click", $);
            this.startPos = [A.pageX, A.pageY];
            this.element.style[B(L + "transition-duration")] = "0ms";
            this.startTime = +new Date;
            this._pos = parseFloat(this.css(this.element, I[this.vertical][1])) || 0
        },
        _move: function(A) {
            if (!this.startPos || A.scale && A.scale !== 1) return;
            A = this.eventHook(A);
            this.stopPos = [A.pageX, A.pageY];
            var $, _ = I[this.vertical][1],
            C = I[this.vertical][0],
            B = this.stopPos[this.vertical] - this.startPos[this.vertical];
            if (this.scrolling || typeof this.scrolling == "undefined" && Math.abs(B) >= Math.abs(this.stopPos[1 - this.vertical] - this.startPos[1 - this.vertical])) {
                A.preventDefault();
                B = B / ((!this.index && B > 0 || this.index == this.length - 1 && B < 0) ? (Math.abs(B) / this[C] + 1) : 1);
                this.element.style[_] = this._pos + B + "px";
                if (J.getSelection != null) {
                    $ = getSelection();
                    if ($.empty) $.empty();
                    else if ($.removeAllRanges) $.removeAllRanges()
                }
                if (B && typeof this.scrolling == "undefined") {
                    this.scrolling = true;
                    clearTimeout(this.timer);
                    clearTimeout(this.aniTimer)
                }
            } else this.scrolling = false
        },
        _end: function(E) {
            if (this.startPos) {
                if (this.scrolling) {
                    var K = I[this.vertical][0],
                    C = I[this.vertical][1],
                    J = this.stopPos[this.vertical] - this.startPos[this.vertical],
                    H = Math.abs(J),
                    A = H / J,
                    _,
                    G,
                    B,
                    D = this.index,
                    F = 0;
                    this.addListener(this.element, "click", $);
                    if (H > 20) {
                        G = parseFloat(this.css(this.element, I[this.vertical][1]));
                        do {
                            if (D >= 0 && D < this.length) {
                                B = this.getPos(K, D);
                                _ = this.getSum(K, D, D + 1)
                            } else {
                                D += A;
                                break
                            }
                        } while ( Math . abs ( B - G ) > _ / 2 && (D -= A)) F = Math.abs(D - this.index);
                        if (!F && +new Date - this.startTime < 250) F = 1
                    }
                    J > 0 ? this.prev(F, false) : this.next(F, false);
                    this.playing && this.play()
                }
                delete this._pos;
                delete this.stopPos;
                delete this.startPos;
                delete this.scrolling;
                delete this.startTime
            }
        },
        mouseScroll: function(C) {
            if (this.cfg.mouseWheel) {
                C = this.eventHook(C);
                var D = this,
                B = C.origEvent,
                _ = 0,
                A = 0,
                $;
                if ("wheelDeltaX" in B) {
                    _ = B.wheelDeltaX;
                    A = B.wheelDeltaY
                } else if ("wheelDelta" in B) A = B.wheelDelta;
                else if ("detail" in B) A = -B.detail;
                else return;
                if (!this.vertical && Math.abs(_) > Math.abs(A)) $ = _;
                else if (A && (!B.wheelDeltaX || this.vertical && Math.abs(_) < Math.abs(A))) $ = A;
                if ($) {
                    C.preventDefault();
                    clearTimeout(this.mouseTimer);
                    this.mouseTimer = setTimeout(function() {
                        $ > 0 ? D.prev(1, false) : D.next(1, false)
                    },
                    100)
                }
            }
        },
        transitionend: function($) {
            if ($.propertyName == I[this.vertical][1]) {
                this.cfg.after.call(this, this.index, this.slides[this.index]);
                this.playing && this.play()
            }
        },
        refresh: function() {
            if (this.direction == null) this.setup();
            else {
                this.slides = E(this.element);
                this.length = this.slides.length;
                this.index = Math.max(Math.min(this.length - 1, this.index), 0);
                this.resize()
            }
        },
        append: function($) {
            this.element.appendChild($);
            this.refresh()
        },
        prepend: function($) {
            this.length ? this.insertBefore($, 0) : this.append($)
        },
        insertBefore: function($, _) {
            this.element.insertBefore($, this.slides[_]);
            if (this.index >= _) this.index++;
            this.refresh()
        },
        remove: function($) {
            this.element.removeChild(this.slides[$]);
            if (this.index >= $) this.index--;
            this.refresh()
        }
    };
    M(["Width", "Height"],
    function(B, A) {
        var $ = A.toLowerCase();
        M(["margin", "padding", "border"],
        function(C, $) {
            _.fn[$ + A] = function(_) {
                return (parseFloat(this.css(_, $ + "-" + I[B][1] + ($ == "border" ? "-width": ""))) || 0) + (parseFloat(this.css(_, $ + "-" + I[B][2] + ($ == "border" ? "-width": ""))) || 0)
            }
        });
        _.fn["get" + A] = function($) {
            return $["offset" + A] - this["padding" + A]($) - this["border" + A]($)
        };
        _.fn["getOuter" + A] = function($) {
            return $["offset" + A] + this["margin" + A]($)
        }
    });
    J.TouchSlider = _
})(window)
